"""
Case Type   : 操作系统类
Case Name   : 主机文件句柄耗尽进行dml操作
Create At   : 2021/7/19
Owner       : @peilinqian
Description :
    1、主节点上执行
    2、连接数据库进行ddl操作
    3、待故障恢复后，再次进行ddl操作
Expect      :
    1、故障注入成功
    2、ddl操作失败，报错“Too many open files”
    3、故障消除后，ddl操作成功
History     :
    Modified by @peilinqian 2024/2/21: 优化用例删除不必要步骤
    Modified by @peilinqian 2024/7/9： 优化用例，增加清理等待时间
"""

import os
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node


class ReliabilityOS(unittest.TestCase):
    nodes = ("PrimaryDbUser", "Standby1DbUser", "Standby2DbUser")

    @RestartDbCluster(*nodes)
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.pri_sh = CommonSH(self.nodes[0])
        self.constant = Constant()
        self.com = Common()
        self.pri_root = Node(node="PrimaryRoot")
        self.inject_time = 60
        self.inject_cmd = f"rfile_deplenish (timeout) values " \
            f"({self.inject_time})"
        self.check_cmd = "df -h"
        self.t_name = 't_os_file_system_case005'

    def test_main(self):
        try:
            step_txt = '----step1:连接主机执行DDL; expect:开始执行----'
            self.log.info(step_txt)
            self.log.info("步骤1:连接主机执行DDL")
            self.ddl_sql = "select pg_sleep(10);" \
                f"drop table if exists {self.t_name} cascade;" \
                f"create table {self.t_name}(id int);" \
                f"insert into {self.t_name} " \
                f"values(generate_series(1,10000));" \
                f"drop table if exists {self.t_name} cascade;" \
                f"select pg_sleep(30);"
            session1 = ComThread(self.pri_sh.executDbSql,
                                 args=(self.ddl_sql,))
            session1.setDaemon(True)
            session1.start()
            time.sleep(5)

            step_txt = '----step2:主节点注入文件句柄耗尽故障; expect:成功----'
            self.log.info(step_txt)
            session = ComThread(self.com.cfe_inject,
                                args=(self.pri_root,
                                      self.inject_cmd))
            session.setDaemon(True)
            session.start()
            self.start_time = time.time()
            self.log.info("-----注入故障结果-----")
            session.join(60)
            result = session.get_result()
            self.log.info(result)
            self.assertIn(self.constant.SUCCESS_CFE_FULL_FILENUM_MSG, result,
                          "执行失败" + step_txt)

            step_txt = '----step3:验证步骤1 DDL结果; expect:报错----'
            self.log.info(step_txt)
            self.log.info("查询DDL结果")
            session1.join(60)
            result = session1.get_result()
            self.log.info(result)
            self.assertIn("Too many open files", result, "执行失败" + step_txt)

        finally:
            text = "-----确认故障清理干净-----"
            self.log.info(text)
            while True:
                time.sleep(5)
                check_msg = self.pri_root.sh(self.check_cmd).result()
                self.log.info(check_msg)
                if self.constant.TOO_MANYY_FILE_MSG not in check_msg:
                    break
                end_time = time.time()
                if end_time - self.start_time > self.inject_time:
                    break

            step_txt = '----step3:再次连接主机执行DDL; expect:成功----'
            self.log.info(step_txt)
            result = self.pri_sh.executDbSql(self.ddl_sql)
            self.log.info(result)
            self.assertNotIn("Too many open files", result, "执行失败" + step_txt)
            self.assertNotIn("ERROR", result, "执行失败" + step_txt)
            self.assertIn("1 row", result, "执行失败" + step_txt)

    def tearDown(self):
        self.log.info("----this is tearDown----")
        step_txt = '----集群状态异常时，恢复环境----'
        self.log.info(step_txt)
        status = self.pri_sh.getDbClusterStatus("status")
        if not status:
            self.result = self.pri_sh.startDbCluster()
            self.final_status = self.pri_sh.getDbClusterStatus("status")

        self.log.info(f'-----{os.path.basename(__file__)} end-----')
        if not status:
            self.assertTrue(self.final_status, "执行失败" + step_txt)
